#include "./inc/http.h"
#include "./inc/uart.h"
#include "./inc/mongoose.h"
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "./inc/cJsonFile.h"
#include "./inc/cJSON.h"

#include <unistd.h>


// 读取文件
int readFileContents(char* filename, char *result, int maxSize)
{
	FILE *fp = NULL;
	fp = fopen(filename, "r");
	char buf[1024] = {0};
	int bufLen = 1024;
	int resultLen = 0;
	while(fgets(buf, 1024, fp) != NULL)
	{
		if(resultLen + strlen(buf) >= maxSize)
		{
			printf("缓冲区满，终止读取\n");
			break;
		}
		const char *hasComment = strchr((const char*)buf, '#'); // 是否有注释存在
		if(!hasComment)
		{
			memcpy(&result[resultLen], buf, strlen(buf));
			resultLen += strlen(buf);
			memset(buf, 0, bufLen);
		}
		else 
		{
			memcpy(&result[resultLen], buf, hasComment - buf);
			resultLen += (hasComment - buf);
			memset(buf, 0, bufLen);
		}
	}
	fclose(fp);
	while(result[resultLen-1] == '\n' || result[resultLen-1] == '\r')
	{
		result[resultLen-1] = '\0';
		resultLen--;
	}
	return resultLen;
}

// 解析json配置文件
cJSON* readJsonFile(char* filename, cJSON*root)
{
	char jsonBuf[10240] = {0};
	int ret = readFileContents(filename, jsonBuf, sizeof(jsonBuf));
	printf("result[%d]:\n%s\n", ret, jsonBuf);
	root = cJSON_Parse((const char*)jsonBuf);
	if(root)
	{
		printf("读取的配置文件:\n %s\n", cJSON_Print(root));
	}
	else
	{
		printf("读取的配置文件出错: %s\n", cJSON_GetErrorPtr());
		exit(1);
	}
	return root;
}

// 根据key修改value
void changeIntValuesByKey(cJSON* root, const char *key, int values)
{
	cJSON_ReplaceItemInObject(root, key, cJSON_CreateNumber(values));
}

void changeDoubleValueByKey(cJSON *root, const char *key, double values )
{
	cJSON_ReplaceItemInObject(root, key, cJSON_CreateNumber(values));
}

void changeStringValueByKey(cJSON* root, const char *key, char* values)
{
	cJSON_ReplaceItemInObject(root, key, cJSON_CreateString(values));
}

// 将json写入文件
int writeJson2File(cJSON *root, char *filename)
{
	FILE *fp = NULL;
	fp = fopen(filename, "w");
	fwrite(cJSON_Print(root), 1, strlen(cJSON_Print(root)), fp);
	fflush(fp);
	fclose(fp);
    sync();
	return 0;
}




#define MAX_SIZE  10240

int mytest(int data)
{

	//char filename[30] = {0};
	char filename[30] = "/app/cfg/svp_parm.json";
	//strcpy(filename, argv[1]);
	char jsonBuf[MAX_SIZE] = {0};
	printf("test01\r\n");
	int ret = readFileContents(filename, jsonBuf, MAX_SIZE);
	//printf("result[%d]:\n%s\n", ret, jsonBuf);

	cJSON* root = NULL;
	root = cJSON_Parse(jsonBuf);
	if(!root)
	{
		printf("读取文件失败: %s\n", cJSON_GetErrorPtr());
		exit(0);
	}
	//printf("%s\n", cJSON_Print(root));

	cJSON* servo_alg = NULL;

	servo_alg = cJSON_GetObjectItem(root, "servo_alg");
	changeIntValuesByKey(root, "servo_alg", data);

	writeJson2File(root, filename);
	return 0;
    
    //return 0;
}



using namespace std;

struct mg_mgr mgr;
struct mg_connection *c;

int w_buf[4] = {0xa0, 0x2D, 0x6C, 0x0a}; //通过串口发送出去的数据
int get_value[2] = {0x0, 0x0};
int y_tmp = 0, x_tmp = 0;

struct termios old_cfg;

pthread_t uartTid = 0;
int fd;
bool init_flag = false;
bool mv_flag = false;

void *UartRecvThread(void *arg)
{

    while (read_write() != 1)
        ;
	sleep(1);

	if(mv_flag == false)
	{
		if(init_flag == false)
			mytest(1);
		if (init_flag == true)
			{
				mytest(2);
				init_flag = false;
			}
	}

	mv_flag = false;
    //tcsetattr(fd, TCSANOW, &old_cfg); //恢复到之前的配置
    std::cout << "uartok!" << std::endl;
    //std::cout << "data" << w_buf[1] << w_buf[2] << std::endl;
    //close(fd);
    return (void *)0;
}


void get_http_value(const char * buf)
{
	cJSON *myroot = cJSON_Parse(buf);
	cJSON *x_json = cJSON_GetObjectItem(myroot, "x_val");
    int x_val = x_json->valuedouble;
    printf("x_val=%d \r\n", x_val);

	cJSON *y_json = cJSON_GetObjectItem(myroot, "y_val");
    int y_val = y_json->valuedouble;
    printf("y_val=%d \r\n", y_val);
	get_value[0]=y_val;
	get_value[1]=x_val;
	cJSON_Delete(myroot);
	return;
}

void handle_download(struct mg_connection *nc, int ev, void *pp)
{

	// 这个my_test置位操作不科学
	// 原理：当发送命令成功一次之后，就置位，不能等全部命令执行完毕之后，再统一置位
    
    struct http_message *hm = (struct http_message *)pp;
    // 这个hm就是全部的信息，解析一下就可以发送给云台舵机了
    std::cout << "my_body_received: " << hm->body.p << std::endl;

	char recived[1];
	strncpy(recived, hm->body.p,1);

    //std::cout << "my_query_string_received: "<< hm->query_string.p <<std::endl;
    std::cout << "over!" << std::endl;

	
	y_tmp =  w_buf[1];
	x_tmp = w_buf[2];

    if (strcmp(recived, "1") == 0) //up
    {
		mv_flag = true;
        y_tmp -= 0x0a;
    }
    else if (strcmp(recived, "2") == 0) //down
    {
		mv_flag = true;
        y_tmp += 0x0a;
    }
    else if (strcmp(recived, "3") == 0) //left
    {
		mv_flag = true;
        x_tmp += 0x0a;
    }
    else if (strcmp(recived, "4") == 0) //right
    {
		mv_flag = true;
        x_tmp -= 0x0a;
    }
	else if (strcmp(recived, "5") == 0) //设定位置
    {
		mytest(0);
		y_tmp = 0x0A; // 转到10度
		x_tmp = 0x0A; // 转到10度
    }
	else if (strcmp(recived, "6") == 0) //归位
    {
		mytest(3);
		init_flag = true;
		y_tmp = 0x2D;
		x_tmp = 0x6C;

    }
	else if (strcmp(recived, "0") == 0) //归位
    {
    }
	else{
	get_http_value(hm->body.p);
	y_tmp =  get_value[0];
	x_tmp = get_value[1];
	}

    if (y_tmp <= 0)
    {
        y_tmp = 0;
    }
    if (y_tmp >= 0x59)
    {
        y_tmp = 0x59;
    }
    if (x_tmp >= 0xd7)
    {
        x_tmp = 0xd7;
    }
    if (x_tmp <= 0)
    {
        x_tmp = 0;
    }

	w_buf[1] = y_tmp ;
	w_buf[2] = x_tmp;

    pthread_create(&uartTid, NULL, UartRecvThread, NULL);

    char out[80 * 1024];

    sprintf(out, "{\"yval\":%d,\"xval\":%d}", w_buf[1], w_buf[2]);
    mg_printf(nc, "HTTP/1.1 200 OK\r\n");
    mg_printf(nc, "Content-Length: %lu\r\n\r\n", strlen(out));
    mg_printf(nc, out);

    
    std::cout << "ok!" << std::endl;
    nc->flags |= MG_F_SEND_AND_CLOSE;
    if (ev == MG_EV_CLOSE)
        return;
    if (hm->query_string.len == 0)
        return;
    return;
}

int main()
{
	mytest(2);
    my_uart_init();
    my_http_init();
    mg_register_http_endpoint(c, "/download", handle_download MG_UD_ARG(NULL));
    for (;;)
    {
        mg_mgr_poll(&mgr, 1000);
    }
    mg_mgr_free(&mgr);
}